use crate::ffmpeg::FfmpegController;

use lazy_static::lazy_static;
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::Child;
use std::sync::{Arc, Mutex};
use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};

const STATUS_IS_RECORDING: &str = "isRecording";
pub struct SharedData {
    output_file: Option<PathBuf>,
    ffmpeg: Option<FfmpegController>,
    //ffmpeg_pid: u32,
    edog: Option<Child>,
    status: Arc<Mutex<HashMap<String, u8>>>,
    hook_status: bool,
    db_sender: Option<std::sync::mpsc::Sender<String>>, // 用于发送数据库操作的消息
}

impl SharedData {
    fn new() -> Self {
        SharedData {
            output_file: None,
            ffmpeg: None,
            // ffmpeg_pid: 0,
            edog: None,
            status: Arc::new(Mutex::new(HashMap::new())),
            hook_status: false,
            db_sender: None,
        }
    }

    pub fn get_output_file(&self) -> Option<&PathBuf> {
        self.output_file.as_ref()
    }

    pub fn set_output_file(&mut self, path: PathBuf) {
        self.output_file = Some(path);
    }

    pub fn stop_ffmpeg(&mut self) -> i32 {
        if let Some(mut fc) = self.ffmpeg.take() {
            let r = fc.wait_stop();
            self.add_status(STATUS_IS_RECORDING.to_string(), 0);
            return r;
        }
        return 0;
    }

    pub fn set_ffmpeg(&mut self, cc: Option<FfmpegController>) {
        if let Some(c) = cc {
            self.ffmpeg.replace(c);
            self.add_status(STATUS_IS_RECORDING.to_string(), 1);
        }
    }

    pub fn set_edog(&mut self, cc: Option<Child>) {
        if let Some(c) = cc {
            self.edog.replace(c);
        } else {
            self.edog.take();
        }
    }
    pub fn get_edog(&mut self) -> Option<&mut Child> {
        self.edog.as_mut()
    }

    pub fn stop_edog(&mut self) -> u32 {
        if let Some(mut process) = self.edog.take() {
            let pid = process.id();
            let _ = process.kill();
            self.edog = None;
            pid
        } else {
            0
        }
    }

    pub fn is_recording(&self) -> bool {
        if let Some(v) = self.status.lock().unwrap().get(STATUS_IS_RECORDING) {
            return *v == 1u8;
        }
        false
    }

    pub fn add_status(&mut self, key: String, value: u8) {
        self.status.lock().unwrap().insert(key, value);
    }

    pub fn get_status(&self, key: Option<String>) -> Arc<Mutex<HashMap<String, u8>>> {
        if let Some(k) = key {
            let mut map = HashMap::new();
            if let Some(v) = self.status.lock().unwrap().get(&k) {
                map.insert(k, v.clone());
            }
            Arc::new(Mutex::new(HashMap::new()))
        } else {
            self.status.clone()
        }
    }
    pub fn set_hook_status(&mut self, status: bool) {
        self.hook_status = status;
    }
    pub fn get_hook_status(&self) -> bool {
        self.hook_status
    }

    pub fn set_db_sender(&mut self, sender: Option<std::sync::mpsc::Sender<String>>) {
        if let Some(tx) = sender {
            self.db_sender.replace(tx);
        } else {
            self.db_sender.take();
        }
    }

    pub fn send_sql(&self, sql: impl AsRef<str>) {
        self.db_sender
            .as_ref()
            .map(|tx: &std::sync::mpsc::Sender<String>| {
                if let Err(e) = tx.send(sql.as_ref().into()) {
                    eprintln!("Failed to send SQL command: {}", e);
                }
            });
    }
}

// unsafe impl Sync for SharedData {}
// 可以使用tauri 状态管理 https://blog.hellagur.com/2022/09/26/%E5%88%9D%E5%A7%8B-Tauri-%E7%AF%87%E5%9B%9B%E4%B9%8B%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86/
lazy_static! {
    static ref GLOBAL_DATA: RwLock<SharedData> = RwLock::new(SharedData::new());
}

pub fn write() -> RwLockWriteGuard<'static, SharedData> {
    GLOBAL_DATA.write().unwrap()
}

pub fn read() -> RwLockReadGuard<'static, SharedData> {
    GLOBAL_DATA.read().unwrap()
}
